package nautilus.moneykeeper.utilities;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import android.content.Context;

public class TaskExecuter {
	public static final int PRIORITY_NORMAL = 0;
	public static final int PRIORITY_BLOCKING = 1;

	private static final Object mLock = new Object();
	private static TaskExecuter mInstance;

	/* For normal tasks */
	private static final int CORE_NORMAL_POOL_SIZE = 4;
	private static final int MAXIMUM_NORMAL_POOL_SIZE = 4;
	private static final int KEEP_ALIVE_TIME = 2;
	private final BlockingQueue<Runnable> mNormalTaskQueue;
	private final ThreadPoolExecutor mTaskThreadPool;

	//For urgent tasks
	private static final int CORE_URGENT_POOL_SIZE = 2;
	private static final int MAXIMUM_URGENT_POOL_SIZE = 2;
	private final BlockingQueue<Runnable> mUrgentTaskQueue;
	private final ThreadPoolExecutor mUrgentTaskThreadPool;

	public static TaskExecuter getInstance(Context context) {
		synchronized (mLock) {
			if (mInstance == null) {
				mInstance = new TaskExecuter(context.getApplicationContext());
			}
			return mInstance;
		}
	}

	private TaskExecuter(Context context) {
		// mAppContext = context;
		mNormalTaskQueue = new LinkedBlockingQueue<Runnable>();
		mTaskThreadPool = new ThreadPoolExecutor(CORE_NORMAL_POOL_SIZE,
				MAXIMUM_NORMAL_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS,
				mNormalTaskQueue);
		mTaskThreadPool.allowCoreThreadTimeOut(true);

		mUrgentTaskQueue = new LinkedBlockingQueue<Runnable>();
		mUrgentTaskThreadPool = new ThreadPoolExecutor(CORE_URGENT_POOL_SIZE,
				MAXIMUM_URGENT_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS,
				mUrgentTaskQueue);
		mUrgentTaskThreadPool.allowCoreThreadTimeOut(true);
	}

	public void execute(Runnable runnable) {
		execute(runnable, PRIORITY_NORMAL);
	}

	
	public void execute(Runnable runnable, int priority) {
		if (priority == PRIORITY_BLOCKING) {
			mUrgentTaskThreadPool.execute(runnable);
		} else {
			mTaskThreadPool.execute(runnable);
		}
	}

	public void cancel(Runnable runnable) {
		mTaskThreadPool.remove(runnable);
		mUrgentTaskThreadPool.remove(runnable);
	}

}
